package de.hska.reka.websockets;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;

import javax.annotation.PostConstruct;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.remoting.support.RemoteExporter;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.ReflectionUtils.MethodCallback;
import org.xlightweb.IWebSocketConnection;
import org.xlightweb.IWebSocketHandler;
import org.xlightweb.TextMessage;
import org.xlightweb.server.HttpServer;

import de.hska.reka.websockets.Parser.JsonRPCParser;
import de.hska.reka.websockets.model.ClassMethod;
import de.hska.reka.websockets.model.ControllerMethodMap;

public class WebSocketServiceExporter extends RemoteExporter implements
		InitializingBean, ApplicationContextAware, IWebSocketHandler {

	private JsonRPCParser jsonRPCParser = new JsonRPCParser();
	private ControllerMethodMap controllerMethodMap = new ControllerMethodMap();
	private List<Class<?>> callbackServices = new LinkedList<Class<?>>(); 

	public List<Class<?>> getCallbackServices() {
		return callbackServices;
	}

	public void setCallbackServices(List<Class<?>> callbackServices) {
		this.callbackServices = callbackServices;
	}

	public void afterPropertiesSet() throws Exception {
		HttpServer httpServer = new HttpServer(8080, this);
		httpServer.start();
	}

	public void setApplicationContext(ApplicationContext arg0)
			throws BeansException {
		// TODO Auto-generated method stub

	}

	public void onConnect(IWebSocketConnection arg0) throws IOException {
		// TODO Auto-generated method stub

	}

	public void onDisconnect(IWebSocketConnection arg0) throws IOException {
		// TODO Auto-generated method stub

	}

	public void onMessage(IWebSocketConnection arg0) throws IOException {
		TextMessage textMessage = arg0.readTextMessage();
		// arg0.writeMessage(new TextMessage(textMessage.toString()));

		String methodName = jsonRPCParser.parseMethodControllerName(textMessage
				.toString());

		try {
			System.out.println(methodName);
			Object[] params = new Object[0];
			this.controllerMethodMap.execute(methodName, params);
		} catch (Exception ex) {
			arg0.writeMessage(new TextMessage(ex.getMessage()));
		}
	}

	@PostConstruct
	public void postConstruct() {
		if (this.getServiceInterface() != null) {
			// iterate over methods and fill controllermethodhashmap
			ReflectionUtils.doWithMethods(this.getServiceInterface(),
					new MethodCallback() {
						public void doWith(Method method)
								throws IllegalArgumentException,
								IllegalAccessException {
							addMethodToMap(method);
						}
					});
		}
	}

	private void addMethodToMap(Method method) {
		if (this.getService() != null) {
			// this.addMethodToMap(method, this.getService());
		}
	}

	public void addMethodToMap(Method method, String beanName) {
		ClassMethod classMethod = new ClassMethod();
		classMethod.setMethod(method);
		classMethod.setBeanName(beanName);

		this.controllerMethodMap.put(beanName.getClass().getName(), classMethod);
	}
}
